//
//  DBManager.m
//  TestDatabase
//
//  Created by a1 technology on 5/28/09.
//  Copyright 2009 __MyCompanyName__. All rights reserved.
//

#import "DBManager.h"

NSMutableArray *queryResult = nil;

static int callback(void *result, int colNo, char **rows, char **cols)
{
	//for(int i = 0; i < colNo; i++,printf("\n"))
//		printf(" c:\n %s:\n r:\n %s",cols[i],rows[i]);
	
	
	//NSMutableArray *resultArr = (NSMutableArray *)result;
	NSMutableArray *resultArr = [[NSMutableArray alloc] init];
	NSDictionary *objectKeyDict = nil;
	NSAutoreleasePool *sqlPool = [[NSAutoreleasePool alloc]init];
	for(int i = 0; i < colNo; i++)
	{
		objectKeyDict = [[NSDictionary alloc] initWithObjectsAndKeys:[NSString stringWithCString:cols[i] encoding:NSASCIIStringEncoding],@"column",[NSString stringWithCString:rows[i]?rows[i]:" " encoding:NSUTF8StringEncoding],@"rows",nil];
		[resultArr addObject:objectKeyDict];
		[objectKeyDict release];
	}	
	[sqlPool release];
	//NSLog(@"DBManager: callback: %@",resultArr);
	[queryResult addObject:resultArr];
	[resultArr release];
	return 0;
}

static int dummmyCallback(void *result, int rowNo, char **rows, char **cols)
{
	return 0;
}

static DBManager *_sharedManager = nil;

@implementation DBManager

@synthesize databaseName;
@synthesize resourceDBPath;
@synthesize docDBpath;

+(DBManager *)sharedManager
{
	if(!_sharedManager)
		_sharedManager = [[self alloc]init];
	return _sharedManager;
}

-(id)init
{
	if(self = [super init])
	{
		database = NULL;
		//[self openDatabaseNamed:@"brainscape-sat.db"];
			
		//resourceDBPath = [[[[NSBundle mainBundle]resourcePath] stringByAppendingPathComponent:@"brainscape-sat.db"]retain];
//		docDBpath = [[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]stringByAppendingPathComponent:@"brainscape-sat.db"]retain];
//		NSFileManager *fileMgr = [NSFileManager defaultManager];
//		if(![fileMgr fileExistsAtPath:docDBpath])
//			[fileMgr copyItemAtPath:resourceDBPath toPath:docDBpath error:nil];
//		if(sqlite3_open([docDBpath UTF8String], &database) != SQLITE_OK)
//			NSLog(@"database unable to open !!");
	}	
	return self;
}

-(BOOL)openDatabaseNamed:(NSString *)newDBName
{
	//NSLog(@"openDatabaseNamed: %@",newDBName);
	BOOL success = YES;
	NSString *newResourceDBPath = [[NSString alloc] initWithString:[[[NSBundle mainBundle]resourcePath] stringByAppendingPathComponent:newDBName]];
	NSString *newDocDBpath = [[NSString alloc] initWithString:[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]stringByAppendingPathComponent:newDBName]];
	//NSLog(@"newResourceDBPath:\n %@\nnewDocDBpath:\n%@",newResourceDBPath,newDocDBpath);
	NSFileManager *fileMgr = [[NSFileManager defaultManager] retain];
	[fileMgr setDelegate:self];
	NSError *err;
	if(!(success = [fileMgr fileExistsAtPath:newDocDBpath]))
		if(!(success = [fileMgr copyItemAtPath:newResourceDBPath toPath:newDocDBpath error:&err]))
			NSLog(@"COPY FAILED:\nfrom: %@\nto: %@\nerror: %@",newResourceDBPath,newDocDBpath,err);
	self.resourceDBPath = newResourceDBPath;
	self.docDBpath = newDocDBpath;
	
	if(database)
		[self closeDB];
	
	if(sqlite3_open([newDocDBpath UTF8String], &database) != SQLITE_OK)
	{
		success = NO;
		//NSLog(@"database unable to open !!");
	}	
	
	[newResourceDBPath release];
	[newDocDBpath release];
	[fileMgr release];
	return success;
}




-(BOOL)executeOutputQuery:(NSString *)query
{
	//query = [self enveloped:query];
	
	BOOL success = YES;
	//int ret = -1;
	//NSLog(@"DBManager: executeOutputQuery: %@ ",query);
	char *queryCStr = (char *)[query cStringUsingEncoding: NSUTF8StringEncoding];
	//NSLog(@"%s",queryCStr);
	char *errorMsg = 0;

	if(queryResult)
		[queryResult release];
	queryResult = [[NSMutableArray alloc] init];
	if(sqlite3_exec(database, queryCStr, callback, 0, &errorMsg) != SQLITE_OK)
	{	
		success = NO;
		printf("database-error: \nQuery: %s\n%s\n",[query UTF8String],errorMsg);
		//NSLog(@"%@",[NSString stringWithFormat:@"@query <%@>: FAILED:%s",query,errorMsg]);
		sqlite3_free(errorMsg);
	}
	//NSLog(@"executeOutputQuery: result: %@",queryResult);
//	NSLog(@"DBManager: executeOutputQuery :%@",success?@"y":@"n");
	return success;
}

-(BOOL)executeInputQuery:(NSString *)query
{
	//if(!([[query componentsSeparatedByString:@"'"]count]%2))
	//query = [self enveloped:query];
	
	NSString *correctQ = [self correctQuery:query];
	
	//NSLog(@"executeInputQuery : %@\n%@",query,correctQ);

	BOOL success = YES;
	char *errorMsg = 0;
	if(sqlite3_exec(database, [correctQ UTF8String], dummmyCallback, 0, &errorMsg) != SQLITE_OK)
	{	
		printf("database-error: \nQuery: %s\n%s\n",[query UTF8String],errorMsg);
		//NSLog([NSString stringWithFormat:@"@query <%@>: FAILED:%s",query,errorMsg]);
		sqlite3_free(errorMsg);
		success = NO;
	}	
	return success;
}

-(NSArray *)queryResult
{
	return queryResult;

}




-(void)closeDB
{
	sqlite3_close(database);
	database = NULL;
}

-(void)dealloc
{
	if(self.resourceDBPath)
		[self.resourceDBPath release];
	if(self.docDBpath)
		[self.docDBpath release];
	if(queryResult)
		[queryResult release];
	[super dealloc];
}

#pragma mark --		NSFileManager	Methods	--
- (BOOL)fileManager:(NSFileManager *)fileManager shouldCopyItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath
{
	//NSLog(@"copying...\nsrc: %@\ndest: %@",srcPath,dstPath);
	return YES;
}

#pragma mark --		Utilities	--
-(NSArray *)simplifiedQueryData
{
	NSMutableArray *simplifiedData = [[NSMutableArray alloc] init];
	for(int row = 0; row < [queryResult count]; row++)
	{
		NSArray *rowData = [queryResult objectAtIndex:row];
		NSMutableArray *rowDataSimplified = [[NSMutableArray alloc] init];
		for(NSDictionary *dict in rowData)
			[rowDataSimplified addObject:[NSDictionary dictionaryWithObject:[dict objectForKey:@"rows"] forKey:[dict objectForKey:@"column"]]];
		[simplifiedData addObject:rowDataSimplified];
		[rowDataSimplified release];
	}	
	return [simplifiedData autorelease];
}

-(NSArray *)processedDataAtRow:(int)rowNo 
{
	NSArray *rowData = [[NSArray alloc] initWithArray:[queryResult objectAtIndex:rowNo]];
	return [rowData autorelease];
}

-(NSDictionary *)processedDataAtRow:(int)rowNo column:(int)colNo
{
	NSArray *rowData = [self processedDataAtRow:rowNo];
	NSDictionary *resultDict = [[NSDictionary alloc] initWithObjectsAndKeys:[[rowData objectAtIndex:0] objectForKey:@"rows"],[[rowData objectAtIndex:0]
																															  objectForKey:@"column"],nil];
	return [resultDict autorelease];
}

//-(NSString *)enveloped:(NSString *)orignalQ
//{
//	NSString *str = [orignalQ stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"\"'"]];
//	int singles = [[str componentsSeparatedByString:@"'"]count]-1;
//	int doubles = [[str componentsSeparatedByString:@"\""]count]-1;
//	NSString *envelope = @"\"";
//	if(!singles)
//		envelope = @"'";
//	NSString *finalStr = [[NSString alloc] initWithFormat:@"%@%@%@",envelope,str,envelope];
//	//NSLog(@"case: %@\nsingle: %d\ndouble: %d\n%@\n\n",str,singles,doubles,finalStr);
//	return [finalStr autorelease];
//}


-(NSString *)correctQuery:(NSString *)aQuery
{
	BOOL outer_block_open = NO;
	NSMutableString *correctedQuery = [[NSMutableString alloc]init];
	
	for(int char_no = 0; char_no < [aQuery length]; char_no++)
	{
		unichar ch = [aQuery characterAtIndex:char_no];
		
		if(ch == '\'')
		{
			if(outer_block_open == NO)
				outer_block_open = YES;
			else if(char_no+1 < [aQuery length])
			{
				unichar nxt_ch = [aQuery characterAtIndex:char_no+1];
				if(nxt_ch == ',' || nxt_ch == ')')
					outer_block_open = NO;
				else
					[correctedQuery appendString:@"'"];
			}	
		}	
		[correctedQuery appendFormat:@"%c",ch];
	}	
	
	return [correctedQuery autorelease];
}


/*
-(NSString *)correctQuery:(NSString *)q
{	
	NSMutableString *newStr = [[NSMutableString alloc]init];
	int alert_mode = 0;	
	
	for(int i = 0; i < [q length]; i++)
	{
		unichar ch = [q characterAtIndex:i];
		if(alert_mode > 1)
			if(ch != ')' || ch != ',')
			{	
				alert_mode = -1;
				[newStr appendString:@"'"];
			}	
		
		[newStr appendFormat:@"%c",ch];
		
		if(ch == '\'')
			alert_mode++;
	}	
	return [newStr autorelease];
}
 */

@end
